﻿using Adnc.Application.Shared.Dtos;
using Adnc.Application.Shared.Enum;
using Adnc.Application.Shared.Services;
using Adnc.Infra.Caching;
using Adnc.Infra.EventBus;
using Adnc.Infra.Helper;
using Adnc.Infra.IRepositories;
using Adnc.Shared.Consts;
using Adnc.Shared.Events;
using Adnc.Shared.RpcServices.Rtos;
using Adnc.Shared.RpcServices.Rtos.Pro;
using Adnc.Shared.RpcServices.Services;
using Microsoft.Extensions.Configuration;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Net;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;
using WYT.Usr.Application.Contracts.Dtos.Warehouse;
using WYT.Usr.Application.Contracts.Services;
using WYT.Usr.Repository.Entities;

namespace WYT.Usr.Application.Services
{
    /// <summary>
    /// 用户云仓服务
    /// </summary>
    public class WarehouseAppService : AbstractAppService, IWarehouseAppService
    {
        private readonly IOrdersRpcService _ordersRpcService;

        private readonly IProductRPCService _productRpcService;

        private readonly IEfRepository<UserRelation> _userRelationRepository;

        private readonly IEfRepository<User> _userRepository;

        private readonly IEfRepository<Warehouse> _warehouseRepository;

        private readonly IEfRepository<WarehouseLog> _warehouseLogRepository;

        private readonly IEfRepository<PExwarehouseLog> _pExwarehouseLogRepository;

        private readonly IEfRepository<Wallet> _walletRepository;

        private readonly IEfRepository<WalletLog> _walletLogRepository;

        private readonly IEfRepository<UserPerformance> _userPerformanceRepository;

        private readonly IEfRepository<UserCommission> _userCommissionRepository;

        private readonly IDistributedLocker _locker;

        private readonly IEventPublisher _eventPublisher;

        /// <summary>
        /// 
        /// </summary>
        /// <param name="ordersRpcService"></param>
        /// <param name="productRpcService"></param>
        /// <param name="userRelationRepository"></param>
        /// <param name="userRepository"></param>
        /// <param name="warehouseRepository"></param>
        /// <param name="warehouseLogRepository"></param>
        /// <param name="pExwarehouseLogRepository"></param>
        /// <param name="walletRepository"></param>
        /// <param name="walletLogRepository"></param>
        /// <param name="userPerformanceRepository"></param>
        /// <param name="userCommissionRepository"></param>
        /// <param name="locker"></param>
        /// <param name="eventPublisher"></param>
        public WarehouseAppService(IOrdersRpcService ordersRpcService
            , IProductRPCService productRpcService
            , IEfRepository<UserRelation> userRelationRepository
            , IEfRepository<User> userRepository
            , IEfRepository<Warehouse> warehouseRepository
            , IEfRepository<WarehouseLog> warehouseLogRepository
            , IEfRepository<PExwarehouseLog> pExwarehouseLogRepository
            , IEfRepository<Wallet> walletRepository
            , IEfRepository<WalletLog> walletLogRepository
            , IEfRepository<UserPerformance> userPerformanceRepository
            , IEfRepository<UserCommission> userCommissionRepository
            , IDistributedLocker locker
            , IEventPublisher eventPublisher)
        {
            _ordersRpcService = ordersRpcService;
            _productRpcService = productRpcService;
            _userRelationRepository = userRelationRepository;
            _userRepository = userRepository;
            _warehouseRepository = warehouseRepository;
            _warehouseLogRepository = warehouseLogRepository;
            _pExwarehouseLogRepository = pExwarehouseLogRepository;
            _walletRepository = walletRepository;
            _walletLogRepository = walletLogRepository;
            _userPerformanceRepository = userPerformanceRepository;
            _userCommissionRepository = userCommissionRepository;
            _locker = locker;
            _eventPublisher = eventPublisher;
        }

        #region 订单出库
        /// <summary>
        /// 库存管理
        /// </summary>
        /// <param name="orderId"></param>
        /// <returns></returns>
        /// <exception cref="NotImplementedException"></exception>
        public async Task<AppSrvResult<bool>> InventoryManagement(long orderId)
        {
            var orderResponse = await _ordersRpcService.GetOrderDetails(orderId);
            if (!orderResponse.IsSuccessStatusCode)
                throw new Exception("订单服务异常");
            var order = orderResponse.Content;

            List<OrderGoodsDto> orderGoods = new List<OrderGoodsDto>();
            foreach (var item in order.OrderGoods)
            {
                if (item.IsGift)
                    continue;

                var sizeDetail = JsonSerializer.Deserialize<ProductSizeDetailRto>(item.ImagesGoods);
                var dto = new OrderGoodsDto
                {
                    OrderGoodsId = item.OrderGoodsId,
                    GoodsId = item.GoodsId,
                    GoodsName = item.GoodsName,
                    SizeId = item.GoodsSizeId,
                    SizeName = sizeDetail.SizeName,
                    GoodsType = sizeDetail.GoodsType,
                    IsThirdParties = sizeDetail.IsThirdParties,
                    Price = sizeDetail.Price,
                    PerformancePrice = sizeDetail.PerformancePrice,
                    Quantity = item.UseDeductionCoupons ? item.Quantity - 1 : item.Quantity,
                    UseDeductionCoupons = item.UseDeductionCoupons,
                    ProxyIntegral = sizeDetail.ProxyIntegral,
                    ShoppingIntegral = sizeDetail.ShoppingIntegral,
                    ProductPrices = sizeDetail.ProductPrices.Select(x => new ProductPriceDto { UserLevel = x.UserLevel, IntegralPrice = x.IntegralPrice, Price = x.Price }).ToList(),
                    WarGoods = sizeDetail.IsSendRepertory ? sizeDetail.GoodsId : sizeDetail.WarGoods ?? 0,
                    WarSize = sizeDetail.IsSendRepertory ? sizeDetail.SizeId : sizeDetail.WarSize ?? 0,
                    WarCount = sizeDetail.IsSendRepertory ? 1 : sizeDetail.WarCount ?? 0,
                    IsThirdCoupons = sizeDetail.IsThirdCoupons,
                    ThirdCommission = sizeDetail.ThirdCommission,
                };
                dto.TotalWarCount = dto.LastWarCount = dto.WarCount * dto.Quantity;

                //益生菌2/3可以从云仓出，1/3从平台出
                if (dto.GoodsType == (int)EnumGoodsType.GOODS_TYPE_PROBIOTICS && dto.WarCount > 1)
                {
                    dto.TotalWarCount = dto.TotalWarCount * 2 / 3;
                    dto.LastWarCount = dto.LastWarCount * 2 / 3;
                }
                orderGoods.Add(dto);
            }

            #region 购物金支付的订单处理
            //购物金支付的单子不出云仓、不算单量
            if (order.PayMode == (int)EnumPayMode.BONUS)
            {
                //检查是否购买了除体验装以外的自营产品
                if (orderGoods.Any(x => x.GoodsType != (int)EnumGoodsType.GOODS_TYPE_SAMPLE && x.IsThirdParties == false))
                    await _userRepository.UpdateRangeAsync(c => c.Id == order.UserId, c => new User { IsUpgrade = true });
                await PlatformExwarehouseLog(order.OrderId, orderGoods);
                return true;
            }
            #endregion

            if (order.OrderType == (int)EnumOrderType.TAKE_HOME)
                await ZTExwarehouse(order, orderGoods);
            else
                await NormalExwarehouse(order, orderGoods);
            return true;
        }

        /// <summary>
        /// 正常出库
        /// </summary>
        /// <param name="order"></param>
        /// <param name="orderGoods"></param>
        /// <returns></returns>
        private async Task NormalExwarehouse(OrderDetailRto order, List<OrderGoodsDto> orderGoods)
        {
            //用户上级关系树
            var userRelations = await _userRelationRepository.Where(c => c.Descendant == order.UserId).ToListAsync();
            var userIds = userRelations.Select(c => c.Ancestor).ToList();
            userIds.Add(order.UserId);

            //用户信息
            var userinfor = _userRepository.Where(c => userIds.Contains(c.Id)).ToList();
            var orderUserInfor = userinfor.Find(c => c.Id == order.UserId);

            //判断订单是否包含自营非体验装商品，并修改用户状态
            if (orderUserInfor.IsUpgrade == false && orderGoods.Any(x => x.GoodsType != (int)EnumGoodsType.GOODS_TYPE_SAMPLE && x.IsThirdParties == false) && !orderUserInfor.IsUpgrade)
                await _userRepository.UpdateRangeAsync(c => c.Id == orderUserInfor.Id, c => new User { IsUpgrade = true });

            //单量
            int proxyIntegrals = 0;
            orderGoods.ForEach(goods =>
            {
                proxyIntegrals += goods.Quantity * goods.ProxyIntegral;
            });

            // 获取返佣列表
            var userCommissionList = GetUserCommissionList(orderUserInfor.Grade, userinfor, userRelations);

            //出库、算返佣、本金和业绩
            await ExwarehouseAndCommission(order, orderUserInfor, orderGoods, userCommissionList);

            //第三方商品直推返佣
            await ThirdCommission(order, orderUserInfor, orderGoods, userCommissionList);

            //订单入库
            if(order.Warehouse)
                await OrderWarehousing(order.UserId,order.OrderId,orderGoods,order.WarehouseType ?? 0);

            //返佣记录
            await SaveCommission(order,userCommissionList);

            //平台出库记录
            await PlatformExwarehouseLog(order.OrderId, orderGoods);

            //修改单量   购买至云仓是不算用户的业绩，出库的时候才算 
            if (proxyIntegrals > 0)
            {
                if(order.Warehouse)
                    userinfor = userinfor.FindAll(x => x.Id != order.UserId);
                userinfor.ForEach(x => x.ProxyIntegral += proxyIntegrals);
                foreach (var item in userinfor)
                    await _userRepository.UpdateAsync(item, UpdatingProps<User>(x => x.ProxyIntegral, x => x.Grade));
            }               

            //保存业绩
            decimal totalPerformance = 0m;
            orderGoods.ForEach(x =>
            {
                if (!x.IsThirdParties && x.GoodsType != (int)EnumGoodsType.GOODS_TYPE_PROBIOTICS)
                    totalPerformance += x.PerformancePrice * x.Quantity;
            });

            //益生菌业绩
            decimal probioticsPerformance = 0m;      
            orderGoods.ForEach(x =>
            {
                if (x.GoodsType == (int)EnumGoodsType.GOODS_TYPE_PROBIOTICS)
                    probioticsPerformance += x.PerformancePrice * x.Quantity;
            });
            //订单中的益生菌如果已出库则不算业绩
            if (!orderGoods.Any(x => x.GoodsType == (int)EnumGoodsType.GOODS_TYPE_PROBIOTICS && x.TotalWarCount != x.LastWarCount))
            {
                userCommissionList.ForEach(x => x.Performance += probioticsPerformance);
                totalPerformance += probioticsPerformance;
            }               

            await SavePerformance(order, totalPerformance, userRelations, userCommissionList);


            //发布用户升级检查事件
            var eventId = IdGenerater.GetNextId();
            var eventData = new UserUpgradeCheckEvent.EventData() { OrderId = order.OrderId, UserIds = userIds.ToArray() };
            var eventSource = System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.FullName;
            await _eventPublisher.PublishAsync(new UserUpgradeCheckEvent(eventId, eventData, eventSource));

            //发布云仓出库结束事件
            var eventId2 = IdGenerater.GetNextId();
            var eventData2 = new OrderExwarehouseCompleteEvent.EventData() { OrderId = order.OrderId };
            var eventSource2 = System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.FullName;
            await _eventPublisher.PublishAsync(new OrderExwarehouseCompleteEvent(eventId2, eventData2, eventSource2));
        }

        /// <summary>
        /// 自提单出库
        /// </summary>
        /// <param name="order"></param>
        /// <param name="orderGoods"></param>
        /// <returns></returns>
        private async Task ZTExwarehouse(OrderDetailRto order, List<OrderGoodsDto> orderGoods)
        {
            var cacheKey = "war:" + order.UserId;
            var flag = await _locker.LockAsync(cacheKey);
            if (!flag.Success)
            {
                await Task.Delay(300);
                flag = await _locker.LockAsync(cacheKey);
            }

            try
            {
                var warehouse = _warehouseRepository.Where(c => c.UserId == order.UserId && c.Quantity > 0).Select(x => new WarehouseChangeDto
                {
                    Id = x.Id,
                    UserId = x.UserId,
                    GoodsId = x.GoodsId,
                    SizeId = x.SizeId,
                    CurrentQuantity = x.Quantity,
                    InitialQuantity = x.Quantity,
                    GoodType = x.GoodsType,
                    WarehouseType = x.Type
                }).ToList();
                List<WarehouseLog> logs = new List<WarehouseLog>();
                var propertyNameAndValues = new Dictionary<long, List<(string propertyName, dynamic propertyValue)>>();
                //库存优先出同规格的商品
                foreach (var item in orderGoods)
                {
                    var wh = warehouse.Where(c => c.SizeId == item.WarSize).OrderByDescending(x => x.WarehouseType).ToList();
                    for (var i = 0; i < wh.Count; i++)
                    {
                        if (wh[i].CurrentQuantity < item.LastWarCount)
                        {
                            item.LastWarCount -= wh[i].CurrentQuantity;
                            wh[i].CurrentQuantity = 0;
                        }
                        else
                        {
                            wh[i].CurrentQuantity -= item.LastWarCount;
                            item.LastWarCount = 0;
                        }
                    }
                }

                //按类型出库
                foreach (var item in orderGoods)
                {
                    if (item.LastWarCount == 0)
                        continue;

                    var whs = warehouse.Where(c => c.GoodType == item.GoodsType).OrderBy(x => x.WarehouseType).ToList();
                    for (var i = 0; i < whs.Count; i++)
                    {
                        if (item.LastWarCount == 0)
                            break;
                        if (whs[i].CurrentQuantity < item.LastWarCount)
                        {
                            item.LastWarCount -= whs[i].CurrentQuantity;
                            whs[i].CurrentQuantity = 0;
                        }
                        else
                        {
                            whs[i].CurrentQuantity -= item.LastWarCount;
                            item.LastWarCount = 0;
                        }
                    }
                }

                if(orderGoods.Any(x => x.LastWarCount > 0))
                    throw new Exception("商品库存不足，出库失败");

                foreach (var item in warehouse)
                {
                    if (item.CurrentQuantity != item.InitialQuantity)
                    {
                        logs.Add(new WarehouseLog()
                        {
                            Id = IdGenerater.GetNextId(),
                            GoodsId = item.GoodsId,
                            SizeId = item.SizeId,
                            Describe = "自提出库",
                            ChangeFrontCoun = item.InitialQuantity,
                            ChangeLaterCoun = item.CurrentQuantity,
                            Count = item.InitialQuantity - item.CurrentQuantity,
                            ChangeType = 2,
                            WarehouseType = item.WarehouseType,
                            Mode = 2,
                            ChangeTime = DateTime.Now,
                            UserId = order.UserId,
                            OrderId = order.OrderId,
                            WarehouseId = item.Id,

                        });
                        propertyNameAndValues.Add(item.Id, new List<(string Column, dynamic Value)>
                        {
                           ("Quantity",item.CurrentQuantity),
                        });
                    }
                }
                await _warehouseRepository.UpdateRangeAsync(propertyNameAndValues);
                await _warehouseLogRepository.InsertRangeAsync(logs);
            }
            finally
            {
                await _locker.SafedUnLockAsync(cacheKey, flag.LockValue);
            }
            //单量
            int ProxyIntegral = orderGoods.Sum(x => x.ProxyIntegral * x.Quantity);
            var user = await _userRepository.FindAsync(order.UserId);
            user.ProxyIntegral += ProxyIntegral;
            await _userRepository.UpdateAsync(user, UpdatingProps<User>(x => x.ProxyIntegral));

            //发布用户升级检查事件
            var eventId = IdGenerater.GetNextId();
            var eventData = new UserUpgradeCheckEvent.EventData() { OrderId = order.OrderId, UserIds = new long[] { user.Id, user.SuperiorUser } };
            var eventSource = System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.FullName;
            await _eventPublisher.PublishAsync(new UserUpgradeCheckEvent(eventId, eventData, eventSource));

            //发布云仓出库结束事件
            var eventId2 = IdGenerater.GetNextId();
            var eventData2 = new OrderExwarehouseCompleteEvent.EventData() { OrderId = order.OrderId };
            var eventSource2 = System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.FullName;
            await _eventPublisher.PublishAsync(new OrderExwarehouseCompleteEvent(eventId2, eventData2, eventSource2));
        }

        /// <summary>
        /// 记录平台出库日志
        /// </summary>
        /// <param name="orderId"></param>
        /// <param name="orderGoods"></param>
        private async Task PlatformExwarehouseLog(long orderId, List<OrderGoodsDto> orderGoods)
        {
            var list = orderGoods.Where(c => c.IsThirdParties == false).ToList();
            List<PExwarehouseLog> logs = new List<PExwarehouseLog>();
            foreach (var item in list)
            {
                if (item.WarCount == 0)
                    logs.Add(new PExwarehouseLog
                    {
                        Id = IdGenerater.GetNextId(),
                        GoodsId = item.GoodsId,
                        SizeId = item.SizeId,
                        OrderId = orderId,
                        OrderGoodsId = item.OrderGoodsId,
                        Quantity = item.UseDeductionCoupons ? item.Quantity + 1 : item.Quantity,
                        Describe = "线上用户下单",
                        CreateTime = DateTime.Now,
                    });
                else
                {
                    if (item.GoodsType == (int)EnumGoodsType.GOODS_TYPE_PROBIOTICS)
                    {
                        logs.Add(new PExwarehouseLog
                        {
                            Id = IdGenerater.GetNextId(),
                            GoodsId = item.GoodsId,
                            SizeId = item.WarSize,
                            OrderId = orderId,
                            OrderGoodsId = item.OrderGoodsId,
                            Quantity = item.UseDeductionCoupons ? item.LastWarCount + item.TotalWarCount / 2 + item.WarCount : item.LastWarCount + item.TotalWarCount / 2,
                            Describe = "线上用户下单",
                            CreateTime = DateTime.Now,
                        });
                    }
                    else if (item.LastWarCount > 0 || item.UseDeductionCoupons)
                    {
                        logs.Add(new PExwarehouseLog
                        {
                            Id = IdGenerater.GetNextId(),
                            GoodsId = item.GoodsId,
                            SizeId = item.WarSize,
                            OrderId = orderId,
                            OrderGoodsId = item.OrderGoodsId,
                            Quantity = item.UseDeductionCoupons ? item.LastWarCount + item.WarCount : item.LastWarCount,
                            Describe = "线上用户下单",
                            CreateTime = DateTime.Now,
                        });
                    }
                }
            }
            await _pExwarehouseLogRepository.InsertRangeAsync(logs);
        }

        /// <summary>
        /// 出库并计算返佣、返本金
        /// </summary>
        /// <param name="order"></param>
        /// <param name="orderUser"></param>
        /// <param name="orderGoods"></param>
        /// <param name="commission"></param>
        /// <returns></returns>
        private async Task ExwarehouseAndCommission(OrderDetailRto order, User orderUser, List<OrderGoodsDto> orderGoods, List<UserCommissionDto> commission)
        {
            var grade = orderUser.Grade;
            //同级返佣金额
            decimal sameLevelCommission = 0; 
            //计算返佣、出库、业绩
            foreach (var item in commission)
            {
                #region 返佣
                //用户的返佣
                decimal Commission = 0;
                //计算返佣
                foreach (var goods in orderGoods)
                {
                    if (goods.IsThirdParties == true)
                        continue;
                    if (goods.GoodsType == (int)EnumGoodsType.GOODS_TYPE_PROBIOTICS)
                    {
                        if (goods.WarCount == 3)
                        {
                            //当前等级价格
                            var currentPrice = goods.ProductPrices.Find(c => c.UserLevel == grade).Price - 30;
                            //上级价格
                            var supGradePrice = goods.ProductPrices.Find(c => c.UserLevel == (item.Grade + (item.IsSameLevel ? 1 : 0))).Price - 30;
                            Commission += (decimal)goods.LastWarCount / 2 * (currentPrice - supGradePrice);
                        }
                        else if (goods.WarCount == 15)
                        {
                            //当前等级价格
                            var currentPrice = goods.ProductPrices.Find(c => c.UserLevel == grade).Price - 150;
                            //上级价格
                            var supGradePrice = goods.ProductPrices.Find(c => c.UserLevel == (item.Grade + (item.IsSameLevel ? 1 : 0))).Price - 150;

                            Commission += (decimal)goods.LastWarCount / 10 * (currentPrice - supGradePrice);
                        }
                    }
                    else
                    {
                        //当前等级价格
                        var currentPrice = goods.ProductPrices.Find(c => c.UserLevel == grade).Price;
                        //上级价格
                        var supGradePrice = goods.ProductPrices.Find(c => c.UserLevel == (item.Grade + (item.IsSameLevel ? 1 : 0))).Price;

                        if (goods.WarCount > 0)
                            Commission += (decimal)goods.LastWarCount / goods.WarCount * (currentPrice - supGradePrice);
                        else
                            Commission += goods.Quantity * (currentPrice - supGradePrice);
                    }
                }

                if (item.IsSameLevel)
                {
                    Commission *= 0.4m;
                    item.Amount = sameLevelCommission = Math.Round(Commission, 2);
                }
                else
                {
                    item.Amount = Math.Round(Commission - sameLevelCommission, 2);
                    sameLevelCommission = 0;
                }
                #endregion

                #region 出库
                // 云仓出库 同级不出库
                if (!item.IsSameLevel)
                {
                    var list = orderGoods.Where(c => c.IsThirdParties == false && c.WarCount > 0 && c.LastWarCount > 0).ToList();
                    if (list.Count > 0)
                    {
                        //分布式锁
                        var cacheKey = "war:" + item.UserId;
                        var flag = await _locker.LockAsync(cacheKey);
                        if (!flag.Success)
                        {
                            await Task.Delay(300);
                            flag = await _locker.LockAsync(cacheKey);
                        }

                        try
                        {
                            var warehouse = _warehouseRepository.Where(c => c.UserId == item.UserId && c.Quantity > 0).WhereIf(order.Warehouse,x => x.Type == 0).Select(x => new WarehouseChangeDto { 
                                Id = x.Id,
                                UserId = x.UserId,
                                GoodsId = x.GoodsId,
                                SizeId = x.SizeId,
                                InitialQuantity = x.Quantity,
                                CurrentQuantity = x.Quantity,
                                GoodType = x.GoodsType,
                                WarehouseType = x.Type
                            }).ToList();
                            
                            //同商品出库
                            foreach (var goods in list)
                            {
                                if (goods.LastWarCount == 0)
                                    break;
                                decimal price = 0;
                                if (goods.GoodsType == (int)EnumGoodsType.GOODS_TYPE_PROBIOTICS)
                                {
                                    if (goods.WarCount == 3)
                                        price = (goods.ProductPrices.Find(c => c.UserLevel == item.Grade).Price - 30) / 2;
                                    else if (goods.WarCount == 15)
                                        price = (goods.ProductPrices.Find(c => c.UserLevel == item.Grade).Price - 150) / 10;
                                }
                                else
                                    price = (goods.ProductPrices.First(c => c.UserLevel == item.Grade).Price) / goods.WarCount;

                                var wh = warehouse.Where(c => c.SizeId == goods.WarSize).OrderByDescending(x=>x.WarehouseType).ToList();
                                for (var i = 0; i < wh.Count; i++)
                                {
                                    if (wh[i].CurrentQuantity < goods.LastWarCount)
                                    {
                                        item.NoChargeBalance += price * wh[i].CurrentQuantity;
                                        goods.LastWarCount -= wh[i].CurrentQuantity;
                                        wh[i].CurrentQuantity = 0;
                                    }
                                    else
                                    {
                                        item.NoChargeBalance += price * goods.LastWarCount;
                                        wh[i].CurrentQuantity -= goods.LastWarCount;
                                        goods.LastWarCount = 0;
                                    }
                                }
                            }
                            //同类型出库
                            foreach (var goods in list)
                            {
                                if (goods.LastWarCount == 0)
                                    break;

                                decimal price = 0;
                                if (goods.GoodsType == (int)EnumGoodsType.GOODS_TYPE_PROBIOTICS)
                                {
                                    if (goods.WarCount == 3)
                                        price = (goods.ProductPrices.Find(c => c.UserLevel == item.Grade).Price - 30) / 2;
                                    else if (goods.WarCount == 15)
                                        price = (goods.ProductPrices.Find(c => c.UserLevel == item.Grade).Price - 150) / 10;
                                }
                                else
                                    price = (goods.ProductPrices.First(c => c.UserLevel == item.Grade).Price) / goods.WarCount;

                                var whs = warehouse.Where(c => c.GoodType == goods.GoodsType).OrderByDescending(x => x.WarehouseType).ToList();
                                for (var i = 0; i < whs.Count; i++)
                                {
                                    if (goods.LastWarCount == 0)
                                        break;
                                    if (whs[i].CurrentQuantity < goods.LastWarCount)
                                    {
                                        item.NoChargeBalance += price * whs[i].CurrentQuantity;
                                        goods.LastWarCount -= whs[i].CurrentQuantity;
                                        whs[i].CurrentQuantity = 0;
                                    }
                                    else
                                    {
                                        item.NoChargeBalance += price * goods.LastWarCount;
                                        whs[i].CurrentQuantity -= goods.LastWarCount;
                                        goods.LastWarCount = 0;
                                    }
                                }
                            }

                            //记录出库数据
                            foreach (var w in warehouse)
                            {
                                if (w.CurrentQuantity < w.InitialQuantity)
                                {
                                    await _warehouseRepository.UpdateAsync(new Warehouse { Id = w.Id, Quantity = w.CurrentQuantity }, UpdatingProps<Warehouse>(x => x.Quantity));
                                    await _warehouseLogRepository.InsertAsync(new WarehouseLog
                                    {
                                        Id = IdGenerater.GetNextId(),
                                        WarehouseId = w.Id,
                                        UserId = w.UserId,
                                        GoodsId = w.GoodsId,
                                        SizeId = w.SizeId,
                                        ChangeFrontCoun = w.InitialQuantity,
                                        Count = w.InitialQuantity - w.CurrentQuantity,
                                        ChangeLaterCoun = w.CurrentQuantity,
                                        ChangeTime = DateTime.Now,
                                        ChangeType = 2,
                                        Mode = 1,
                                        WarehouseType = w.WarehouseType,
                                        OrderId = order.OrderId,
                                        Describe = "线上用户下单【上级库存不足，云仓出库】"
                                    });
                                }
                            }
                        }
                        finally
                        {
                            await _locker.SafedUnLockAsync(cacheKey, flag.LockValue);
                        }
                    }
                }

                #endregion

                #region 业绩
                foreach (var goods in orderGoods)
                {
                    //自营、非益生菌商品计算业绩
                    if (!goods.IsThirdParties && goods.GoodsType != (int)EnumGoodsType.GOODS_TYPE_PROBIOTICS)
                    {
                        if(goods.WarCount > 0)
                            item.Performance += (decimal)goods.LastWarCount / goods.WarCount * goods.PerformancePrice;
                        else 
                            item.Performance += goods.Quantity * goods.PerformancePrice;
                    }
                        
                }
                #endregion
                grade = item.Grade;
            }
        }

        /// <summary>
        /// 第三方商品返佣
        /// </summary>
        /// <param name="order"></param>
        /// <param name="orderUser"></param>
        /// <param name="orderGoods"></param>
        /// <param name="commission"></param>
        /// <returns></returns>
        private async Task ThirdCommission(OrderDetailRto order, User orderUser, List<OrderGoodsDto> orderGoods, List<UserCommissionDto> commission)
        {
            if (orderGoods.Any(x => x.IsThirdParties == true))
            {
                var ThirdCoupons = orderGoods.FindAll(x => x.IsThirdParties == true && x.IsThirdCoupons);
                var Nomal = orderGoods.FindAll(x => x.IsThirdParties == true && x.IsThirdCoupons == false);
                if (Nomal.Any())
                {
                    decimal sameLevelCommission = 0;
                    var grade = orderUser.Grade;
                    foreach (var item in commission)
                    {
                        decimal Commission = 0;
                        foreach (var goods in Nomal)
                        {
                            //当前等级价格
                            var currentPrice = goods.ProductPrices.Find(c => c.UserLevel == grade).Price;
                            //上级价格
                            var supGradePrice = goods.ProductPrices.Find(c => c.UserLevel == (item.Grade + (item.IsSameLevel ? 1 : 0))).Price;
                            Commission += goods.Quantity * (currentPrice - supGradePrice);
                        }

                        if (item.IsSameLevel)
                        {
                            Commission *= 0.4m;
                            item.ThirdPartyAmount = sameLevelCommission = Math.Round(Commission, 2);
                        }
                        else
                        {
                            item.ThirdPartyAmount = Math.Round(Commission - sameLevelCommission, 2);
                            sameLevelCommission = 0;
                        }
                        grade = item.Grade;
                    }
                }

                if (ThirdCoupons.Any())
                {
                    decimal Commission = ThirdCoupons.Sum(x => x.ThirdCommission * x.Quantity);
                    if (order.Reference.HasValue && order.Reference > 0)
                    {
                        var com = commission.FirstOrDefault(x => x.UserId == order.Reference.Value);
                        if (com == null)
                        {
                            var user = await _userRepository.FindAsync(order.Reference.Value);
                            if (user == null)
                                com = new UserCommissionDto { UserId = orderUser.Id, Grade = orderUser.Grade };
                            else
                                com = new UserCommissionDto { UserId = user.Id, Grade = user.Grade };
                            commission.Add(com);
                        }
                        com.ThirdPartyAmount = Commission;
                    }
                    else
                    {
                        commission.Add(new UserCommissionDto { UserId = orderUser.Id, Grade = orderUser.Grade, ThirdPartyAmount = Commission });
                    }
                }
            }
        }

        /// <summary>
        /// 保存返佣
        /// </summary>
        /// <param name="order"></param>
        /// <param name="userCommissionList"></param>
        /// <returns></returns>
        private async Task SaveCommission(OrderDetailRto order, List<UserCommissionDto> userCommissionList)
        {
            List<UserCommission> addList = new List<UserCommission>();
            foreach (var item in userCommissionList)
            {
                if (item.Amount > 0)
                    addList.Add(new UserCommission
                    {
                        Id = IdGenerater.GetNextId(),
                        UserId = item.UserId,
                        CurrentGrade = item.Grade,
                        Amount = item.Amount,
                        OrderId = order.OrderId,
                        Type = 1,
                        State = 1,
                        CreateTime = DateTime.Now,
                        ArrivalTime = DateTime.Now,
                    });
                if (item.NoChargeBalance > 0)
                    addList.Add(new UserCommission
                    {
                        Id = IdGenerater.GetNextId(),
                        UserId = item.UserId,
                        CurrentGrade = item.Grade,
                        Amount = item.NoChargeBalance,
                        OrderId = order.OrderId,
                        Type = 2,
                        State = 1,
                        CreateTime = DateTime.Now,
                        ArrivalTime= DateTime.Now,
                    });
                if (item.ThirdPartyAmount > 0)
                    addList.Add(new UserCommission
                    {
                        Id = IdGenerater.GetNextId(),
                        UserId = item.UserId,
                        CurrentGrade = item.Grade,
                        Amount = item.ThirdPartyAmount,
                        OrderId = order.OrderId,
                        Type = 3,
                        State = 0,
                        CreateTime = DateTime.Now,
                    });
            }

            if (addList.Any())
            {
                await _userCommissionRepository.InsertRangeAsync(addList);
                var users = addList.Where(x => x.State == 1).Select(x => x.UserId).Distinct().ToList();
                foreach (var user in users)
                {
                    var list = addList.FindAll(x => x.UserId == user && x.State == 1);
                    if (!list.Any())
                        continue;
                    var cacheKey = "wallet:" + user;
                    var flag = await _locker.LockAsync(cacheKey);
                    if (!flag.Success)
                    {
                        await Task.Delay(300);
                        flag = await _locker.LockAsync(cacheKey);
                    }

                    try
                    {
                        var wallet = await _walletRepository.FindAsync(c => c.UserId == user);
                        if (wallet == null)
                        {
                            wallet = new Wallet
                            {
                                Id = IdGenerater.GetNextId(),
                                UserId = user
                            };
                            await _walletRepository.InsertAsync(wallet);
                        }
                        List<WalletLog> logs = new List<WalletLog>();

                        foreach (var com in list)
                        {
                            if (com.Type == 1)
                            {
                                var shoppingMoney = Math.Round(com.Amount * 0.1m, 2);       //购物金
                                var balance = com.Amount - shoppingMoney;                  //余额

                                WalletLog walletLog1 = new WalletLog
                                {
                                    Id = IdGenerater.GetNextId(),
                                    UserId = com.UserId,
                                    Mode = 2,
                                    ChangeAmount = balance,
                                    ChangeMode = 1,
                                    Amount = balance,
                                    ChangeFrontImage = JsonSerializer.Serialize(wallet),
                                    ChangeFrontMoney = wallet.Balance,
                                    SourceOrder = com.Id,
                                    Describe = "返佣",
                                    WalletType = 1,
                                    CreateTime = DateTime.Now
                                };
                                wallet.ChargeBalance += balance;
                                wallet.Balance += balance;
                                walletLog1.ChangeLaterMoney = wallet.Balance;
                                walletLog1.ChangedLaterImage = JsonSerializer.Serialize(wallet);
                                logs.Add(walletLog1);

                                WalletLog walletLog2 = new WalletLog
                                {
                                    Id = IdGenerater.GetNextId(),
                                    UserId = com.UserId,
                                    Mode = 2,
                                    ChangeAmount = shoppingMoney,
                                    ChangeMode = 1,
                                    Amount = shoppingMoney,
                                    ChangeFrontImage = JsonSerializer.Serialize(wallet),
                                    ChangeFrontMoney = wallet.ShoppingMoney,
                                    WalletType = 2,
                                    Describe = "返佣",
                                    SourceOrder = com.Id,
                                    CreateTime = DateTime.Now
                                };
                                wallet.ShoppingMoney += shoppingMoney;
                                walletLog2.ChangeLaterMoney = wallet.ShoppingMoney;
                                walletLog2.ChangedLaterImage = JsonSerializer.Serialize(wallet);
                                logs.Add(walletLog2);
                            }
                            else if (com.Type == 2)
                            {
                                WalletLog walletLog = new WalletLog
                                {
                                    Id = IdGenerater.GetNextId(),
                                    UserId = com.UserId,
                                    Mode = 2,
                                    ChangeAmount = com.Amount,
                                    ChangeMode = 1,
                                    Amount = com.Amount,
                                    ChangeFrontImage = JsonSerializer.Serialize(wallet),
                                    ChangeFrontMoney = wallet.Balance,
                                    SourceOrder = com.Id,
                                    Describe = "本金",
                                    WalletType = 1,
                                    CreateTime = DateTime.Now
                                };
                                wallet.Balance += com.Amount;
                                wallet.NoChargeBalance += com.Amount;
                                walletLog.ChangeLaterMoney = wallet.Balance;
                                walletLog.ChangedLaterImage = JsonSerializer.Serialize(wallet);
                                logs.Add(walletLog);
                            }
                        }
                        await _walletRepository.UpdateAsync(wallet, UpdatingProps<Wallet>(c => c.NoChargeBalance, c => c.ShoppingMoney, c => c.ChargeBalance, c => c.Balance));
                        await _walletLogRepository.InsertRangeAsync(logs);
                    }
                    finally
                    {
                        await _locker.SafedUnLockAsync(cacheKey, flag.LockValue);
                    }
                }
            }
        }

        /// <summary>
        /// 订单商品入库
        /// </summary>
        /// <param name="userId"></param>
        /// <param name="orderId"></param>
        /// <param name="order"></param>
        /// <param name="warehouseType"></param>
        /// <returns></returns>
        private async Task OrderWarehousing(long userId, long orderId,  List<OrderGoodsDto> order,int warehouseType = 0)
        {
            //订单入库
            var cacheKey = "war:" + userId;
            var flag = await _locker.LockAsync(cacheKey);
            if (!flag.Success)
            {
                await Task.Delay(300);
                flag = await _locker.LockAsync(cacheKey);
            }

            try
            {
                var list = await _warehouseRepository.Where(c => c.UserId == userId && c.Type == warehouseType).ToListAsync();
                List<Warehouse> nwlist = new List<Warehouse>();
                List<WarehouseLog> whlogs = new List<WarehouseLog>();
                foreach (var item in order)
                {
                    var wh = list.FirstOrDefault(c => c.SizeId == item.SizeId);
                    var log = new WarehouseLog()
                    {
                        Id = IdGenerater.GetNextId(),
                        UserId = userId,
                        OrderId = orderId,
                        GoodsId = item.GoodsId,
                        SizeId = item.SizeId,
                        ChangeType = 1,
                        Mode = 3,
                        WarehouseType = 0,
                        Count = item.Quantity,
                        ChangeTime = DateTime.Now,
                        Describe = "云仓进货"
                    };
                    if (wh != null)
                    {
                        log.WarehouseId = wh.Id;
                        log.ChangeFrontCoun = wh.Quantity;
                        wh.Quantity += item.Quantity;
                        wh.GoodsType = item.GoodsType;
                        log.ChangeLaterCoun = wh.Quantity;

                        await _warehouseRepository.UpdateAsync(wh, UpdatingProps<Warehouse>(c => c.Quantity, x => x.GoodsType));
                    }
                    else
                    {
                        wh = new Warehouse()
                        {
                            Id = IdGenerater.GetNextId(),
                            GoodsId = item.GoodsId,
                            SizeId = item.SizeId,
                            Quantity = item.Quantity,
                            UserId = userId,
                            GoodsType = item.GoodsType,
                        };
                        log.WarehouseId = wh.Id;
                        log.ChangeFrontCoun = 0;
                        log.ChangeLaterCoun = wh.Quantity;

                        await _warehouseRepository.InsertAsync(wh);
                    }
                    whlogs.Add(log);
                }

                await _warehouseLogRepository.InsertRangeAsync(whlogs);
            }
            finally
            {
                await _locker.SafedUnLockAsync(cacheKey, flag.LockValue);
            }
        }

        /// <summary>
        /// 保存业绩
        /// </summary>
        /// <param name="order"></param>
        /// <param name="totalPerformance">总业绩</param>
        /// <param name="userRelations">关系链</param>
        /// <param name="commissions"></param>
        /// <returns></returns>
        private async Task SavePerformance(OrderDetailRto order, decimal totalPerformance, List<UserRelation> userRelations, List<UserCommissionDto> commissions)
        {
            if (totalPerformance == 0)
                return;
            
            List<UserPerformance> performances = new List<UserPerformance>();
            //门店进货不算自己业绩
            if (order.OrderType != (int)EnumOrderType.OPEN_UP)
            {
                performances.Add(new UserPerformance
                {
                    Id = IdGenerater.GetNextId(),
                    Date = new DateTime(DateTime.Now.Year, DateTime.Now.Month, 1),
                    UserID = order.UserId,
                    CreateTime = DateTime.Now,
                    Performance = totalPerformance,
                    SourceOrderId = order.OrderId,
                    Describe = "自购"
                });
            }

            if (commissions.Count == 0)
            {
                foreach (var item in userRelations)
                    performances.Add(new UserPerformance
                    {
                        Id = IdGenerater.GetNextId(),
                        Date = new DateTime(DateTime.Now.Year, DateTime.Now.Month, 1),
                        UserID = item.Ancestor,
                        CreateTime = DateTime.Now,
                        Performance = totalPerformance,
                        SourceOrderId = order.OrderId,
                        Describe = "下级订单"
                    });
            }
            else
            {
                var performance = totalPerformance;
                var level = 1;
                for (var i = 0; i < commissions.Count; i++)
                {
                    if (performance <= 0)
                        break;

                    userRelations.FindAll(x => x.Level < commissions[i].Level && x.Level >= level).ForEach(x => performances.Add(new UserPerformance
                    {
                        Id = IdGenerater.GetNextId(),
                        Date = new DateTime(DateTime.Now.Year, DateTime.Now.Month, 1),
                        UserID = x.Ancestor,
                        CreateTime = DateTime.Now,
                        SourceOrderId = order.OrderId,
                        Performance = performance,
                        Describe = "下级购买"
                    }));
                    performance = commissions[i].Performance;
                    level = commissions[i].Level;
                }

                if(performance > 0)
                {
                    userRelations.FindAll(x => x.Level >= commissions.Last().Level).ForEach(x => performances.Add(new UserPerformance
                    {
                        Id = IdGenerater.GetNextId(),
                        Date = new DateTime(DateTime.Now.Year, DateTime.Now.Month, 1),
                        UserID = x.Ancestor,
                        CreateTime = DateTime.Now,
                        Performance = performance,
                        SourceOrderId = order.OrderId,
                        Describe = "下级购买"
                    }));
                }

            }

            if (performances.Count > 0)
                await _userPerformanceRepository.InsertRangeAsync(performances);
        }

        /// <summary>
        /// 获取返佣列表
        /// </summary>
        /// <param name="grade"></param>
        /// <param name="userExtends"></param>
        /// <param name="userRelations"></param>
        /// <returns></returns>
        private List<UserCommissionDto> GetUserCommissionList(int grade, List<User> userExtends, List<UserRelation> userRelations)
        {
            //返佣列表
            List<UserCommissionDto> userCommissionList = new List<UserCommissionDto>();
            var v = from ur in userRelations
                    join ue in userExtends on ur.Ancestor equals ue.Id
                    orderby ur.Level ascending
                    where ue.State != 2
                    select new
                    {
                        ue.Id,
                        ue.Grade,
                        ur.Level
                    };
            var data = v.ToList();

            bool hasSameLevel = false;
            //查找出库和同级列表
            for (var i = 0; i < data.Count; i++)
            {
                //V5没有同级返佣
                if (grade >= 7)
                    break;
                if (data[i].Grade > grade)
                {
                    userCommissionList.Add(new UserCommissionDto() { UserId = data[i].Id, Grade = data[i].Grade, Level = data[i].Level, IsSameLevel = false });
                    grade = data[i].Grade;
                    hasSameLevel = false;
                }
                else if (data[i].Grade == grade && !hasSameLevel && grade > 1)    //零售没有同级返佣
                {
                    userCommissionList.Add(new UserCommissionDto() { UserId = data[i].Id, Grade = data[i].Grade, Level = data[i].Level, IsSameLevel = true });
                    hasSameLevel = true;
                }
                else if (data[i].Grade < grade)
                {
                    hasSameLevel = true;
                }
            }

            return userCommissionList;
        }

        #endregion

        #region 云仓管理

        /// <summary>
        /// 获取出库日志
        /// </summary>
        /// <param name="userId"></param>
        /// <param name="input"></param>
        /// <returns></returns>
        public async Task<AppSrvResult<PageModelDto<WarehouseLogDto>>> GetUserWarehouseLogList(long userId, WarehouseLogSearchDto input)
        {
            var iszh = input.IsZh();

            var count = await _warehouseLogRepository.CountAsync(c =>c.UserId == userId && c.ChangeType == input.Type && c.ChangeTime >= input.StartTime  && c.ChangeTime <= input.EndTime);
            var data = await _warehouseLogRepository.Where(c =>c.UserId == userId && c.ChangeType == input.Type && c.ChangeTime >= input.StartTime && c.ChangeTime <= input.EndTime)
                .OrderByDescending(c =>c.ChangeTime)
                .Skip(input.PageSize * (input.PageIndex - 1))
                .Take(input.PageSize)
                .Select(c => Mapper.Map<WarehouseLogDto>(c))
                .ToListAsync();

            if(data.Any())
            {
                var sizeIds = data.Select(x => x.SizeId).ToArray();
                var productResponse = await _productRpcService.GetProductSizeSimpleInforByIds(sizeIds);
                if (!productResponse.IsSuccessStatusCode)
                    return Problem(HttpStatusCode.BadRequest, "服务异常");
                var Sizes = productResponse.Content;
                data.ForEach(x => {
                    var size = Sizes.First(x => x.SizeId == x.SizeId);
                    x.SizeName = iszh ? size.SizeName : size.UighurSizeName;
                    x.GoodsName = iszh ? size.GoodsName : size.UighurGoodsName;
                });
            }
            return new PageModelDto<WarehouseLogDto>(input.PageIndex,input.PageSize, data, count);
        }

        /// <summary>
        /// 获取用户云仓商品总的数量
        /// </summary>
        /// <param name="userId"></param>
        /// <returns></returns>
        public async Task<AppSrvResult<int>> GetUserWarehouseCount(long userId)
        {
            return await _warehouseRepository.Where(c => c.UserId == userId).SumAsync(c => c.Quantity);
        }

        /// <summary>
        /// 获取用户云仓商品列表
        /// </summary>
        /// <param name="userId"></param>
        /// <param name="input"></param>
        /// <returns></returns>
        public async Task<AppSrvResult<List<WarehouseDto>>> GetUserWarehouse(long userId, SearchDto input)
        {
            bool isZh = input.Language.Equals(LanguageConsts.ZH);

            var whereCondition = ExpressionCreator.New<Warehouse>()
                              .And(c => c.UserId == userId);

            var data = await _warehouseRepository.Where(whereCondition)
                .GroupBy(x => x.SizeId)
                .Select(x => new {
                   SizeId = x.Key,
                   Quantity = x.Sum(c => c.Quantity)
                }).ToListAsync();
            List<WarehouseDto> result = new List<WarehouseDto>();
            if (data.Any())
            {
                var sizeIds = data.Select(c => c.SizeId).ToArray();
                var productResponse = await _productRpcService.GetProductSizeDetailByIds(sizeIds, false);
                if (!productResponse.IsSuccessStatusCode)
                    return Problem(HttpStatusCode.BadRequest, "服务异常");
                var products = productResponse.Content;
                foreach (var item in data)
                {
                    var product = products.First(c => c.SizeId == item.SizeId);
                    result.Add(new WarehouseDto()
                    {
                        GoodsId = product.GoodsId,
                        GoodsName = isZh ? product.GoodsName : product.UighurGoodsName,
                        SizeId = item.SizeId,
                        SizeName = isZh ? product.SizeName : product.UighurSizeName,
                        Quantity = item.Quantity,
                        SurfacePlot = isZh ? product.SurfacePlot : product.UighurSurfacePlot,
                    });
                }
            }

            return result;
        }

        /// <summary>
        /// 分类获取云仓商品
        /// </summary>
        /// <param name="userId"></param>
        /// <param name="language"></param>
        /// <returns></returns>
        public async Task<AppSrvResult<List<WarehouseClassificationDto>>> ClassificationGetUserWarehouse(long userId,string language)
        {
            bool isZh = language.Equals(LanguageConsts.ZH);
            var warehouse = await _warehouseRepository.Where(x => x.UserId == userId && x.Quantity > 0).ToListAsync();
            var data = warehouse.GroupBy(x => x.GoodsType)
                .Select(x => new Tuple<long, int>(x.Key,x.Sum(c => c.Quantity)))
                .ToList();

            var productResponse = await _productRpcService.GetAllWarProduct();
            if (!productResponse.IsSuccessStatusCode)
                return Problem(HttpStatusCode.BadRequest, "服务异常");
            var products = productResponse.Content;

            return products.GroupBy(x => x.GoodsType).Select(x => new WarehouseClassificationDto
            {
                GoodsType = x.Key,
                Quantity = (data.FirstOrDefault(c => c.Item1 == x.Key)?.Item2) ?? 0,
                WarehouseList = x.Select(c => new WarehouseDto { 
                    GoodsId = c.GoodsId,
                    SizeId = c.SizeId,
                    GoodsName = c.GoodsName,
                    SizeName = c.SizeName,
                    Quantity = warehouse.FindAll(y => y.SizeId == c.SizeId).Sum(x => x.Quantity),
                    SurfacePlot = isZh ? c.SurfacePlot : c.UighurSurfacePlot,
                }).ToList(),
            }).ToList();
        }

        /// <summary>
        /// 获取用户云仓商品数量
        /// </summary>
        /// <param name="userId"></param>
        /// <param name="sizeIds"></param>
        /// <returns></returns>
        public async Task<AppSrvResult<List<WarehouseSimpleDto>>> GetWarehouseSimplesAsync(long userId)
        {
           return await  _warehouseRepository.Where(x => x.UserId == userId)
                .Select(x => new WarehouseSimpleDto { GoodsId = x.GoodsId,SizeId = x.SizeId,Quantity = x.Quantity,GoodsType = x.GoodsType}).ToListAsync();
        }

        #endregion

        /// <summary>
        /// 订单收货后处理
        /// </summary>
        /// <param name="orderId"></param>
        /// <returns></returns>
        public async Task<AppSrvResult> OrderReceivingHandle(long orderId)
        { 
            var data = await _userCommissionRepository.Where(x => orderId == x.OrderId && x.State == 0).ToListAsync();
            if (data.Count > 0)
            {
                foreach (var item in data)
                {
                    var cacheKey = "wallet:" + item.UserId;
                    var flag = await _locker.LockAsync(cacheKey);
                    if (!flag.Success)
                    {
                        await Task.Delay(300);
                        flag = await _locker.LockAsync(cacheKey);
                    }

                    try
                    {
                        var wallet = await _walletRepository.FindAsync(c => c.UserId == item.UserId);
                        if (wallet == null)
                        {
                            wallet = new Wallet
                            {
                                Id = IdGenerater.GetNextId(),
                                UserId = item.UserId
                            };
                            await _walletRepository.InsertAsync(wallet);
                        }
                        List<WalletLog> logs = new List<WalletLog>();

                        if (item.Type == 3)
                        {
                            var ShoppingMoney = Math.Round(item.Amount * 0.1m, 2);       //购物金
                            var ChargeBalance = item.Amount - ShoppingMoney;

                            WalletLog walletLog1 = new WalletLog
                            {
                                Id = IdGenerater.GetNextId(),
                                UserId = item.UserId,
                                Mode = 2,
                                ChangeAmount = ChargeBalance,
                                ChangeMode = 1,
                                Amount = ChargeBalance,
                                ChangeFrontImage = JsonSerializer.Serialize(wallet),
                                ChangeFrontMoney = wallet.ChargeBalance,
                                SourceOrder = item.Id,
                                Describe = "返佣",
                                WalletType = 1,
                                CreateTime = DateTime.Now
                            };
                            wallet.ChargeBalance += ChargeBalance;
                            wallet.Balance += ChargeBalance;
                            walletLog1.ChangeLaterMoney = wallet.Balance;
                            walletLog1.ChangedLaterImage = JsonSerializer.Serialize(wallet);
                            logs.Add(walletLog1);

                            WalletLog walletLog2 = new WalletLog
                            {
                                Id = IdGenerater.GetNextId(),
                                UserId = item.UserId,
                                Mode = 2,
                                ChangeAmount = ShoppingMoney,
                                ChangeMode = 1,
                                Amount = ShoppingMoney,
                                ChangeFrontImage = JsonSerializer.Serialize(wallet),
                                ChangeFrontMoney = wallet.ShoppingMoney,
                                WalletType = 2,
                                Describe = "返佣",
                                SourceOrder = item.Id,
                                CreateTime = DateTime.Now
                            };
                            wallet.ShoppingMoney += ShoppingMoney;
                            walletLog2.ChangeLaterMoney = wallet.ShoppingMoney;
                            walletLog2.ChangedLaterImage = JsonSerializer.Serialize(wallet);
                            logs.Add(walletLog2);
                        }

                        await _walletRepository.UpdateAsync(wallet, UpdatingProps<Wallet>(c => c.NoChargeBalance, c => c.ShoppingMoney, c => c.ChargeBalance, c => c.Balance));
                        await _walletLogRepository.InsertRangeAsync(logs);
                        item.State = 1;
                        item.ArrivalTime = DateTime.Now;

                        await _userCommissionRepository.UpdateAsync(item, UpdatingProps<UserCommission>(x => x.State, x => x.ArrivalTime));
                    }
                    finally
                    {
                        await _locker.SafedUnLockAsync(cacheKey, flag.LockValue);
                    }
                }                
            }
            return AppSrvResult();
        }
    }
}
